package kpi.javatraining6.gnatiuk.src.tester;

import java.lang.reflect.Field;
import java.util.*;

import kpi.javatraining6.gnatiuk.src.tester.inout.Input;
import kpi.javatraining6.gnatiuk.src.tester.question.Question;
import kpi.javatraining6.gnatiuk.src.tester.user.User;
import kpi.javatraining6.gnatiuk.src.tester.user.UserProgress;


public class QuestionnaireController {
	private static final String QUIT_COMMAND="quit";
	private static final String BACK_COMMAND="back";
	private static final String HELP="help";

	private boolean finishedQuestionnaire;
	private Questionnaire questionnaire;
    private Map<String, Questionnaire> questionnaireMap;
	private Question currentQuestion;
    private UserProgress currentProgress;
    private User user;
    private List<String> topicList;

	public QuestionnaireController(User user,  Map<String, Questionnaire> questionnaireMap){
        this.questionnaireMap = questionnaireMap;
		finishedQuestionnaire = false;
		currentQuestion = null;
        this.user = user;
        topicList = new LinkedList<>();
	}

    /**
     * runs questionnaire.
     * gets random question from a list.
     */
    public void run() {
        ArrayList<Questionnaire> questionnaires = new ArrayList<>(questionnaireMap.values());
        Random rnd = new Random();
        fillAnsweredQuestions(questionnaires);
        while (!questionnaires.isEmpty()){
            if (questionnaire == null){
                questionnaire = questionnaires.get(rnd.nextInt(questionnaires.size()));
                currentProgress = user.getCurrentProgress(questionnaire.getTopic());
            }
            if (questionnaire.hasMoreQuestions(currentProgress.getCurrentDifficulty())){
                initiateQuestionStep();
            } else {
                questionnaires.remove(questionnaire);
                questionnaire = null;
            }
            if (finishedQuestionnaire) {
                break;
            }
        }
        finishQuestionnaire();
    }

    private void fillAnsweredQuestions(ArrayList<Questionnaire> questionnaires) {
          for (Questionnaire questionnaire: questionnaires) {
              UserProgress lastProgress = user.getCurrentProgress(questionnaire.getTopic());
              for (int questionIndex = 0; questionIndex < lastProgress.getAnsweredQuestionsNumber(); questionIndex++) {
                questionnaire.addToAnswered(lastProgress.getAnsweredQuestion(questionIndex));
              }
          }
    }

    private void initiateQuestionStep() {
            currentQuestion = questionnaire.nextQuestion(currentProgress.getCurrentDifficulty());
            if (currentProgress.isAnswered(currentQuestion)) {
                questionnaire.addToAnswered(currentQuestion);
            }else{
                displayQuestion();
                ArrayList<String> answers = Input.getInstance().readAnswer();
                processAnswer(answers);
            }
    }

    private void displayQuestion() {
        System.out.println(currentQuestion);
        System.out.println(String.format("Enter answer or a command e.g. \"%s\"", HELP));
    }

    private void finishQuestionnaire() {
        if(finishedQuestionnaire){
            System.out.println("Questionnaire was closed");
            Logger.getInstance().recordUserAction(user.getUserName(), "user left");
            finishedQuestionnaire = false;
        }else{
            System.out.println("You finished this questionnaire");
            Logger.getInstance().recordUserAction(user.getUserName(), "finished");
        }
        Logger.getInstance().recordUserAction(user.getUserName(), "finished");
    }

	private void processAnswer(ArrayList<String> answers){
		help(answers);
	}

	/**
	 * Command for quit
	 */
	private void quit(ArrayList<String> answersArray) {
		if (answersArray.get(0).equals(QUIT_COMMAND)) {
			finishedQuestionnaire = true;
		} else {
			back(answersArray);
		}
	}

	/**
	 * Command for putBack
	 */
	private void back(ArrayList<String> answersArray) {
		if (answersArray.get(0).equals(BACK_COMMAND)) {
			questionnaire.putBack(currentQuestion);
            String prevTopic = getPreviousTopic(questionnaire.getTopic());
            currentProgress = user.getCurrentProgress(prevTopic);
			currentProgress.removeLastAnswered();
            questionnaire = questionnaireMap.get(prevTopic);
            questionnaire.putBackLastAnswered();
		} else {
			answerTheQuestion(answersArray);
		}
	}

    private String getPreviousTopic(String prevTopic) {
        if (topicList.size() > 0) {
            int lastIndex = getLastTopicIndex();
            prevTopic = topicList.get(lastIndex);
            topicList.remove(lastIndex);
        }
        return prevTopic;
    }

    private int getLastTopicIndex() {
        int lastIndex = topicList.size() - 1;
        if (lastIndex < 0) {
            lastIndex = 0;
        }
        return lastIndex;
    }

    public void answerTheQuestion(ArrayList<String> answerArray) {
		questionnaire.addToAnswered(currentQuestion);
        currentProgress.addToAnswered(currentQuestion, answerArray);
        topicList.add(questionnaire.getTopic());
        questionnaire = null;
    }

    private void help(ArrayList<String> answerArray){
		if (answerArray.get(0).equals(HELP)) {
            System.out.println(getCommands());
		} else {
			quit(answerArray);
		}
	}

	private String getCommands(){
		String commands="";
		Class<QuestionnaireController> thisObject = QuestionnaireController.class;
		Field[] publicFields = thisObject.getDeclaredFields();
		int number=1;
		for (Field field : publicFields) {
			if(field.getType().getName().equals(String.class.getName())){
				try {
					commands+=String.format("%d. %s\n",number++, field.get(field.getName()).toString());
				} catch (IllegalArgumentException | IllegalAccessException e) {
					e.printStackTrace();
				}
            }
		}
		return commands;
	}
}
